import * as tstl from 'typescript-to-lua';
import * as ts from 'typescript';
import * as lua from 'typescript-to-lua/dist/LuaAST';
import { FunctionVisitor } from "typescript-to-lua/dist/transformation/context";
import { transformInPrecedingStatementScope } from "typescript-to-lua/dist/transformation/utils/preceding-statements";
import { checkVariableDeclarationList, transformVariableDeclaration } from "typescript-to-lua/dist/transformation/visitors/variable-declaration";
import { invertCondition, transformLoopBody } from 'typescript-to-lua/dist/transformation/visitors/loops/utils';
console.log("for_rule loaded");
const for_rule = {
    visitors: {
        [ts.SyntaxKind.ForStatement]: (node: ts.ForStatement, context: tstl.TransformationContext) => {
            const initializer = node.initializer;
            const condition = node.condition;
            const incrementor = node.incrementor;
            if (!initializer || !condition || !incrementor) {
                return convertToWhileLoop(node, context);
            }
            if (ts.isVariableDeclarationList(initializer) && initializer.declarations.length === 1) {
                const declaration = node.initializer.declarations[0];
                if (ts.isIdentifier(declaration.name) && declaration.initializer && ts.isBinaryExpression(condition)) {
                    const varName = declaration.name.text;
                    if (!ts.isIdentifier(condition.left) || condition.left.text !== varName) {
                        return convertToWhileLoop(node, context); // 使用自定义回退
                    }
                    let controlVariable, limit;
                    let start = context.transformExpression(declaration.initializer!);
                    //console.log("for_rule: ", start);
                    let step = lua.createNumericLiteral(1);
                    let conditionRight = context.transformExpression(condition.right);
                    // 处理不同比较运算符
                    switch (condition.operatorToken.kind) {
                        case ts.SyntaxKind.LessThanToken:         // i < end
                            limit = conditionRight;
                            break;
                        case ts.SyntaxKind.LessThanEqualsToken:   // i <= end
                            limit = conditionRight; // 直接使用右值作为限制
                            break;
                        case ts.SyntaxKind.GreaterThanToken:      // i > end
                            limit = conditionRight;
                            step = lua.createNumericLiteral(-1);
                            break;
                        case ts.SyntaxKind.GreaterThanEqualsToken: // i >= end
                            limit = conditionRight; // 同上，直接使用右值，配合 step 为 -1
                            step = lua.createNumericLiteral(-1);
                            break;
                        default:
                            return convertToWhileLoop(node, context); // 使用自定义回退
                    }
                    const stepResult = analyzeStepExpression(incrementor, varName, context);
                    if (!stepResult.valid) 
                    {
                        return convertToWhileLoop(node, context);
                    }
                    if (stepResult.step) {
                        step = stepResult.step;
                        if (isStepDirectionConflict(condition.operatorToken.kind, step)) {
                            return convertToWhileLoop(node, context);
                        }
                    }
                    if (ts.isVariableDeclaration(declaration) && declaration.name.kind === ts.SyntaxKind.Identifier) {
                        controlVariable = lua.createIdentifier(declaration.name.getText());
                    }
                    let body: tstl.Block = lua.createBlock(transformLoopBody(context, node));
                    return lua.createForStatement(body, controlVariable, start, limit, step, node);
                }
            }
            return convertToWhileLoop(node, context);
        }
    }
};


/**
 * 分析步长表达式，并将其转换为 Lua 代码。
 *
 * @param incrementor 步长表达式（TypeScript 表达式）。
 * @param varName 变量名（字符串）。
 * @param context 转换上下文（tstl.TransformationContext）。
 * @returns 返回对象，包含两个属性：valid（是否有效）和 step（步长表达式，可能是 null）。
 */
function analyzeStepExpression(incrementor: ts.Expression, varName: string, context: tstl.TransformationContext) {
    let step: tstl.Expression | null = null;
    let valid = true;

    if (ts.isPostfixUnaryExpression(incrementor) || ts.isPrefixUnaryExpression(incrementor)) {
        // 处理 i++ 或 ++i
        //console.log("for_rule: ", incrementor.operator);
        if (incrementor.operator === ts.SyntaxKind.PlusPlusToken) {
            step = tstl.createNumericLiteral(1);
        } else if (incrementor.operator === ts.SyntaxKind.MinusMinusToken) {
      
            step = tstl.createNumericLiteral(-1);
        }
    } 
    else if (ts.isBinaryExpression(incrementor)) {
        // 处理  += -=  （*= /= for 处理不了放在while里面处理） 
        if (incrementor.operatorToken.kind === ts.SyntaxKind.PlusEqualsToken ||
            incrementor.operatorToken.kind === ts.SyntaxKind.MinusEqualsToken ||
            incrementor.operatorToken.kind === ts.SyntaxKind.AsteriskEqualsToken ||
            incrementor.operatorToken.kind === ts.SyntaxKind.SlashEqualsToken  
        ) {
            if (ts.isIdentifier(incrementor.left) && incrementor.left.text === varName) 
            {
                const baseValue = incrementor.operatorToken.kind === ts.SyntaxKind.PlusEqualsToken ? 1 : -1;
                if (ts.isNumericLiteral(incrementor.right)) 
                {
                    step = tstl.createNumericLiteral(
                        baseValue * parseInt(incrementor.right.text)
                    );
                } 
                else {
                    const transformed = context.transformExpression(incrementor.right);
                    step =  incrementor.operatorToken.kind === ts.SyntaxKind.MinusEqualsToken ?
                        tstl.createUnaryExpression(transformed, '-') :
                        transformed;
                }
            }
        }
    }
    return { valid: !!step, step };
}

/**
 * 判断给定的运算符和步长是否冲突。
 *
 * @param operator TypeScript语法类型（SyntaxKind），表示运算符。
 * @param step TypeScript AST（抽象语法树）表达式，表示步长。
 * @returns 如果运算符和步长冲突，则返回true；否则返回false。
 */
function isStepDirectionConflict(operator: ts.SyntaxKind, step: tstl.Expression) {
    const isNegativeStep = tstl.isNumericLiteral(step) && Number(step.value) < 0;
    return (
        (operator === ts.SyntaxKind.LessThanToken || //小于等于
            operator === ts.SyntaxKind.LessThanEqualsToken) && isNegativeStep
    ) || (
            (operator === ts.SyntaxKind.GreaterThanToken ||
                operator === ts.SyntaxKind.GreaterThanEqualsToken) && !isNegativeStep //大于等于
        );
}


/**
 * 将 TypeScript 的 for 循环语句转换为 Lua 的 while 循环语句。
 *
 * @param statement TypeScript 的 for 循环语句对象。
 * @param context 转换上下文。
 * @returns 转换后的 Lua 语句对象。
 */
function convertToWhileLoop(statement: ts.ForStatement, context: tstl.TransformationContext): lua.Statement {
    const result: lua.Statement[] = [];
    if (statement.initializer) {
        if (ts.isVariableDeclarationList(statement.initializer)) {
            checkVariableDeclarationList(context, statement.initializer);
            result.push(...statement.initializer.declarations.flatMap(d => transformVariableDeclaration(context, d)));
        } else {
            result.push(...context.transformStatements(ts.factory.createExpressionStatement(statement.initializer)));
        }
    }
    const body: lua.Statement[] = transformLoopBody(context, statement);
    let condition: lua.Expression;
    if (statement.condition) {
        const tsCondition = statement.condition;
        const { precedingStatements: conditionPrecedingStatements, result } = transformInPrecedingStatementScope(
            context,
            () => context.transformExpression(tsCondition)
        );
        condition = result;
        if (conditionPrecedingStatements.length > 0) {
            conditionPrecedingStatements.push(
                lua.createIfStatement(
                    invertCondition(condition),
                    lua.createBlock([lua.createBreakStatement()]),
                    undefined,
                    statement.condition
                )
            );
            body.unshift(...conditionPrecedingStatements);
            condition = lua.createBooleanLiteral(true);
        }
    } else {
        condition = lua.createBooleanLiteral(true);
    }
    if (statement.incrementor) {
        body.push(...context.transformStatements(ts.factory.createExpressionStatement(statement.incrementor)));
    }
    // while (condition) do ... end
    result.push(lua.createWhileStatement(lua.createBlock(body), condition, statement));
    return lua.createDoStatement(result, statement);
}
module.exports = for_rule;